package com.yxhl.zoume.core.expresscar.presenter;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.DrawableRes;
import android.text.TextUtils;

import com.amap.api.maps.AMap;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.route.BusRouteResult;
import com.amap.api.services.route.DrivePath;
import com.amap.api.services.route.DriveRouteResult;
import com.amap.api.services.route.RideRouteResult;
import com.amap.api.services.route.RouteSearch;
import com.amap.api.services.route.WalkRouteResult;
import com.yxhl.protobuf.BizOrder;
import com.yxhl.protobuf.BizOrderResponse;
import com.yxhl.protobuf.Location;
import com.yxhl.protobuf.OrderBizType;
import com.yxhl.protobuf.OrderPayStatus;
import com.yxhl.protobuf.OrderRideStatus;
import com.yxhl.protobuf.ServiceType;
import com.yxhl.protobuf.TcpRequest;
import com.yxhl.protobuf.TcpResponse;
import com.yxhl.zoume.R;
import com.yxhl.zoume.ZouMeApplication;
import com.yxhl.zoume.common.presenter.BasePresenter;
import com.yxhl.zoume.common.ui.view.BaseView;
import com.yxhl.zoume.core.expresscar.view.ExpressCarScheduleMapView;
import com.yxhl.zoume.core.func.map.ZMDrivingRouteOverlay;
import com.yxhl.zoume.core.func.tcp.TcpRequestProvider;
import com.yxhl.zoume.core.specialcar.model.MarkerCategory;
import com.yxhl.zoume.core.specialcar.model.MarkerType;
import com.yxhl.zoume.data.tcp.OnChannelListener;
import com.yxhl.zoume.utils.LOG;
import com.yxhl.zoume.utils.StringUtils;
import com.yxhl.zoume.utils.tcp.TcpService;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.inject.Inject;

/**
 * Author：zhongshan   
 * Date：2016/12/09 11:48      
 * Description：ExpressCarScheduleMapPresenter
 */
public class ExpressCarScheduleMapPresenter extends BasePresenter implements AMap.OnMapClickListener, ServiceConnection {
    private static final String TAG = "ExpressCarScheduleMapPresenter";
    private AMap aMap;
    private RouteSearch mRouteSearch;
    private String mOrderSerial;
    private ExpressCarHandler mExpressCarHandler;
    private TcpService.TcpClientController mTcpClientController;
    private ExpressCarScheduleMapView scheduleMapView;
    private ZMDrivingRouteOverlay mDrivingRouteOverlay;
    private boolean isRouteSearched = false;
    private Timer timer;
    private Context mContext;
    private boolean isMarkShow;

    private static final int TCP_REQUEST_PERIOD = 10 * 1000;
    private static final int WHAT_TCP_RESPONSE = 1;
    private int mLastRideStatus = OrderRideStatus.ORIS_DEFAULT_VALUE;
    private ArrayList<MarkerOptions> mMarkerOptionsList;
    private OrderBizType orderBizType;

    /**
     * 订单超时,对话框是否弹出标示
     */
    private boolean mIsFirstTimeRunTimeOut = true;


    @Inject
    public ExpressCarScheduleMapPresenter(Context context) {
        super(context);
        mContext = context;
    }

    @Override
    public void attachView(BaseView view) {
        super.attachView(view);
        if (view instanceof ExpressCarScheduleMapView) {
            scheduleMapView = (ExpressCarScheduleMapView) view;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    public void init(AMap aMap) {
        this.aMap = aMap;
        mRouteSearch = new RouteSearch(mContext);
        registerListener();
    }

    private void registerListener() {
        aMap.setOnMapClickListener(this);
        mRouteSearch.setRouteSearchListener(new RouteSearch.OnRouteSearchListener() {
            @Override
            public void onBusRouteSearched(BusRouteResult busRouteResult, int i) {

            }

            @Override
            public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) {
                handleDriveRouteSearchedResult(driveRouteResult, i);
            }

            @Override
            public void onWalkRouteSearched(WalkRouteResult walkRouteResult, int i) {

            }

            @Override
            public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {

            }
        });
    }

    /**
     * 开启Tcp轮询
     */
    public void startPolling(Activity activity, final String orderId) {
        mOrderSerial = orderId;
        mExpressCarHandler = new ExpressCarHandler(Looper.getMainLooper());
        bindTcpService(activity);
    }

    /**
     * ＊停止Tcp轮询
     */
    public boolean stopPolling(Activity activity) {
        return unbindTcpService(activity);
    }

    private void bindTcpService(final Activity activity) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(activity, TcpService.class);
                activity.bindService(intent, ExpressCarScheduleMapPresenter.this, Context.BIND_AUTO_CREATE);
            }
        }).start();
    }

    private boolean unbindTcpService(Activity activity) {
        mTcpClientController.closeChannel();
        activity.unbindService(this);
        return true;
    }

    //bind service listener
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        mTcpClientController = (TcpService.TcpClientController) service;
        mTcpClientController.startTcpConnection(new OnChannelListener() {
            @Override
            public void onChannelActive() {

            }

            @Override
            public void onChannelInactive() {
                handleChannelInactive();
            }

            @Override
            public void onConnectionSuccess() {
                handleChannelConnectionSuccess();
            }

            @Override
            public void onChannelRead(TcpResponse tcpResponse) {
                if (tcpResponse != null)
                    handleChannelRead(tcpResponse);
            }
        });
    }

    //bind service listener
    @Override
    public void onServiceDisconnected(ComponentName name) {

    }

    //RouteSearchListener
    private void handleDriveRouteSearchedResult(DriveRouteResult driveRouteResult, int errorCode) {
        if (errorCode == 1000
                && driveRouteResult != null
                && driveRouteResult.getPaths() != null
                && driveRouteResult.getPaths().size() > 0) {
            // 1.线路规划标记
            isRouteSearched = true;
            // 2.1线路规划
            final DrivePath drivePath = driveRouteResult.getPaths().get(0);
            mDrivingRouteOverlay = new ZMDrivingRouteOverlay(mContext, aMap, drivePath,
                    driveRouteResult.getStartPos(), driveRouteResult.getTargetPos());
            mDrivingRouteOverlay.setThroughPointIconVisibility(true);
            // 设置途径转弯处用户不可见,以免干扰途径点
            mDrivingRouteOverlay.setNodeIconVisibility(false);
            mDrivingRouteOverlay.removeFromMap();
            mDrivingRouteOverlay.addToMap();
            //  zoomToSpan();
            // 2.2线路规划完成事件
//                    RxBus.getInstance().send(new RouteSearchCompleteEvent());
            // 3.添加终点marker
            //      addArriveStationMark();
        } else {
            scheduleMapView.routeResultFailure();
        }
    }

    private void handleChannelInactive() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    /**
     * channel connection success ,start polling
     */
    private void handleChannelConnectionSuccess() {
        if (timer == null) {
            timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (!TextUtils.isEmpty(mOrderSerial)) {
                        TcpRequestProvider requestProvider = TcpRequestProvider.getInstance().init(mContext, mOrderSerial);
                        TcpRequest tcpRequest = requestProvider.getTcpRequest(ServiceType.USER_QUERY_LOC);
                        mTcpClientController.sendTcpRequest(tcpRequest);
                    }
                }
            }, 0, TCP_REQUEST_PERIOD);
        }
    }

    /**
     * receive tcp server response
     */
    private void handleChannelRead(TcpResponse tcpResponse) {
        if (tcpResponse.getIsSucc()) {
            BizOrderResponse bizOrderResp = tcpResponse.getBizOrderResp();
            orderBizType = bizOrderResp.getOrderBizType();
            // send handle message
            if (bizOrderResp.getOrderBizType() == OrderBizType.SPECIAL_BUS_TIME
                    || bizOrderResp.getOrderBizType() == OrderBizType.SPECIAL_BUS_WAY) {
                Message msg = mExpressCarHandler.obtainMessage();
                msg.obj = bizOrderResp;
                msg.what = WHAT_TCP_RESPONSE;
                mExpressCarHandler.sendMessage(msg);
            }
        }
    }

    /**
     * handle express car ui
     */
    private void scheduleUi(BizOrderResponse bizOrderResponse) {
        List<BizOrder> orderFieldsesList = bizOrderResponse.getOrderFieldsesList();
//        OrderPayStatus payStatus1 = bizOrderResponse.getPayStatus();
        BizOrder bizOrder = orderFieldsesList.get(0);
//        OrderPayStatus payStatus = bizOrder.getPayStatus();
        OrderPayStatus payStatus = bizOrderResponse.getPayStatus();
        if (OrderPayStatus.PAID.equals(payStatus)) {
            scheduleMapView.showArrivalDialog(bizOrderResponse);
            return;
        }
        switch (bizOrderResponse.getRideStatus()) {
            //订单预约中，未派车
            case UN_SEND:
                calculateExpressCarRoute(bizOrderResponse);

                //订单超时 失效
                if (payStatus.equals(OrderPayStatus.PAY_CANCEL)) {
                    if (mIsFirstTimeRunTimeOut) {
                        scheduleMapView.showTimeOutDialog();
                        mIsFirstTimeRunTimeOut = !mIsFirstTimeRunTimeOut;
                    }
                }

                if (mLastRideStatus < OrderRideStatus.UN_SEND_VALUE) {
                    showOrderUnSendUI();
                }
                //司机拒绝接任务,订单状态回滚到未派车
                else if (mLastRideStatus == OrderRideStatus.UN_TAKEN_VALUE) {
                    //开启ScheduleBar退出动画
                    scheduleMapView.startExitAnimatorForScheduleBar();
                    //更新ScheduleBar数据
                    scheduleMapView.updateDataBetweenRideStatus(
                            OrderRideStatus.UN_TAKEN_VALUE,
                            OrderRideStatus.UN_SEND_VALUE,
                            bizOrderResponse.getDriverTel());
                    showOrderUnSendUI();
                }
                break;
            //订单提交成功,正在派车中
            case UN_TAKEN:
                calculateExpressCarRoute(bizOrderResponse);
                //第一次轮询到该状态时
                if (mLastRideStatus <= OrderRideStatus.UN_SEND_VALUE) {
                    showOrderUnTakenUi(bizOrderResponse);
                }
                break;
            //乘客上车,行程中
            case TAKEN:
                calculateExpressCarRoute(bizOrderResponse);
                if (payStatus.equals(OrderPayStatus.OPS_SEND_BILL)) {
                    scheduleMapView.showPaymentDialog(bizOrderResponse);
                } else {
                    String runTime = bizOrderResponse.getRunTime();
                    String runDistance = bizOrderResponse.getRunDistance();
                    scheduleMapView.updateTimeAndDistanceValue(runTime, runDistance);
                    if (mLastRideStatus <= OrderRideStatus.UN_TAKEN_VALUE) {
                        showOrderTakenUi(bizOrderResponse);
                    }
                }
                break;
            //已到站,去评论
            case ARRIVED:
                if (mLastRideStatus <= OrderRideStatus.TAKEN_VALUE) {
                    showArrivedUi(bizOrderResponse);
                }
                break;
            case RIDE_INVALID:
                showOrderOutOfDateUI();
                break;
            case DROP:
                showOrderFinishUI();
                break;

        }
    }

    /**
     * 展示任务关闭UI
     */
    private void showOrderFinishUI() {
        if (mLastRideStatus <= OrderRideStatus.RIDE_INVALID.getNumber()) {
            //设置Toolbar
            scheduleMapView.setupToolBarHeaderStatus(
                    ZouMeApplication.application.getString(R.string.special_car_operation_cancel_trip),
                    ""
            );

            //显示对话框
            scheduleMapView.showInvalidDataDialog();

            //更新乘车状态
            mLastRideStatus = OrderRideStatus.DROP.getNumber();

        }
    }

    /**
     * 展示任务失效UI
     */
    private void showOrderOutOfDateUI() {
        if (mLastRideStatus <= OrderRideStatus.ARRIVED.getNumber()) {
            //设置Toolbar
            scheduleMapView.setupToolBarHeaderStatus(
                    ZouMeApplication.application.getString(R.string.route_detail_cancel_charter),
                    ""
            );

            //显示对话框
            scheduleMapView.showDriverCloseDialog();

            //更新乘车状态
            mLastRideStatus = OrderRideStatus.RIDE_INVALID.getNumber();
        }
    }

    /**
     * 已到站，去评论
     */
    private void showArrivedUi(BizOrderResponse bizOrderResponse) {
        //更新ToolBar
        scheduleMapView.setupToolBarHeaderStatus(mContext.getString(R.string.route_detail_finish_charter), "");
        if (mLastRideStatus != OrderRideStatus.ORIS_DEFAULT_VALUE) {
            //DriverInfo退出动画
            scheduleMapView.startExitAnimatorForDriverInfo();
        }
        //退出时间,里程统计栏
        scheduleMapView.startTimeDistanceInfoBarAnimator(false);
        //行程结束对话框
        scheduleMapView.showArrivalDialog(bizOrderResponse);

        //更新乘车状态
        mLastRideStatus = OrderRideStatus.ARRIVED_VALUE;
    }

    /**
     * 已乘车，行程中
     */
    private void showOrderTakenUi(BizOrderResponse bizOrderResponse) {

        //更新ToolBar
        scheduleMapView.setupToolBarHeaderStatus(mContext.getString(R.string.route_detail_take_charter), "");

        //更新DriverInfo
        String driverCarInfo = bizOrderResponse.getVehicleSeries() + " " + bizOrderResponse.getVehicleNo();
        int judgePoint = (int) bizOrderResponse.getDriverJudgePoint();

        scheduleMapView.setupDriverInfoStatus(StringUtils.getCalledName(bizOrderResponse.getDriverName()), driverCarInfo, judgePoint, true, bizOrderResponse.getDriverTel());

        if (mLastRideStatus != OrderRideStatus.ORIS_DEFAULT_VALUE) {
            //退出ScheduleBar动画
            scheduleMapView.startExitAnimatorForScheduleBar();
        } else {
            scheduleMapView.startEnterAnimatorForDriverInfoAndScheduleBar(false);
        }

        if (bizOrderResponse.getOrderBizType() == OrderBizType.SPECIAL_BUS_TIME) {
            //开启时间/里程统计栏
            scheduleMapView.startTimeDistanceInfoBarAnimator(true);
        } else {
            scheduleMapView.startTimeDistanceInfoBarAnimator(false);
        }
        //更新乘车状态
        mLastRideStatus = OrderRideStatus.TAKEN_VALUE;
    }

    /**
     * 未乘车，接驾中
     */
    private void showOrderUnTakenUi(BizOrderResponse bizOrderResponse) {
        //1.更新DriverIno信息
        String driverCarInfo = bizOrderResponse.getVehicleSeries() + " " + bizOrderResponse.getVehicleNo();
        int judgePoint = (int) bizOrderResponse.getDriverJudgePoint();

        scheduleMapView.setupDriverInfoStatus(StringUtils.getCalledName(bizOrderResponse.getDriverName()), driverCarInfo, judgePoint, true, bizOrderResponse.getDriverTel());

        //2.更新Toolbar信息
        scheduleMapView.setupToolBarHeaderStatus(
                mContext.getString(R.string.route_detail_wait_charter),
                mContext.getString(R.string.special_car_operation_cancel_trip)
        );

        //3.开启过度动画,true,表示由上一个状态过度来的,则需要开启移除上一个状态出现的行程信息栏动画
        if (mLastRideStatus != OrderRideStatus.ORIS_DEFAULT_VALUE) {
            scheduleMapView.startExitAnimatorForScheduleBar();
        }
        //4.更新乘车状态
        scheduleMapView.updateDataBetweenRideStatus(
                OrderRideStatus.UN_SEND_VALUE,
                OrderRideStatus.UN_TAKEN_VALUE,
                bizOrderResponse.getDriverTel());

        scheduleMapView.startEnterAnimatorForDriverInfoAndScheduleBar(true);
        mLastRideStatus = OrderRideStatus.UN_TAKEN_VALUE;
    }

    /**
     * 未派车，等待接驾
     */
    private void showOrderUnSendUI() {
        //更新Toolbar
        scheduleMapView.setupToolBarHeaderStatus(
                mContext.getString(R.string.route_detail_no_charter),
                mContext.getString(R.string.special_car_operation_cancel_trip)
        );
        //弹出ScheduleBar动画
        scheduleMapView.startEnterAnimatorForScheduleBar();
        //更新乘车状态
        mLastRideStatus = OrderRideStatus.UN_SEND_VALUE;
    }

    /**
     * calculate express car route
     */
    private void calculateExpressCarRoute(BizOrderResponse bizOrderResponse) {
        if (bizOrderResponse.getOrderBizType() == OrderBizType.SPECIAL_BUS_WAY) {
            LatLonPoint startPoint = null;
            LatLonPoint endPoint = null;
            //配置线路的起点,终点
            if (bizOrderResponse.getLnglatsCount() > 0) {
                Location selfInfo = bizOrderResponse.getLnglats(0);
                startPoint = new LatLonPoint(Double.valueOf(selfInfo.getLat()), Double.valueOf(selfInfo.getLng()));//起点，
            }
            if (bizOrderResponse.getElnglatsCount() > 0) {
                Location arriveInfo = bizOrderResponse.getElnglats(0);
                endPoint = new LatLonPoint(Double.valueOf(arriveInfo.getLat()), Double.valueOf(arriveInfo.getLng()));//终点，
            }
            final RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(startPoint, endPoint);
            // 第一个参数表示路径规划的起点和终点，第二个参数表示驾车模式，第三个参数表示途经点，第四个参数表示避让区域，第五个参数表示避让道路
            RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(fromAndTo,
                    RouteSearch.DrivingDefault, null, null, "");
            // 异步路径规划驾车模式查询
            mRouteSearch.calculateDriveRouteAsyn(query);
        }
    }

    //MapClickListener
    @Override
    public void onMapClick(LatLng latLng) {

    }

    /**
     * 更新专车地图覆盖物－分时租车
     *
     * @param aMap
     * @param LatLngList
     */
    public void refreshExpressCarTimingMarkersInMap(AMap aMap, List<Location> LatLngList) {
        refreshMarkShow();
        if (aMap != null) {
            //清空地图上所有覆盖物
            aMap.clear();
            addCurrentLocationMarkerOptions(LatLngList);
            addMarker(aMap);
        }
    }

    /**
     * 更新专车地图覆盖物－单程用车
     *
     * @param aMap
     * @param LatLngList
     * @param eLatLngList
     */
    public void refreshExpressCarMileageMarkersInMap(AMap aMap, List<Location> LatLngList, List<Location> eLatLngList) {
        refreshMarkShow();
        if (aMap != null) {
            //清空地图上所有覆盖物
            aMap.clear();
            addCurrentLocationMarkerOptions(LatLngList);
            addArrivedLoactionMarkerOptions(eLatLngList);
            addMarker(aMap);
        }
    }

    private void addCurrentLocationMarkerOptions(List<Location> LatLngList) {
        if (mMarkerOptionsList == null) {
            mMarkerOptionsList = new ArrayList<>();
        }
        mMarkerOptionsList.clear();
        if (LatLngList != null && LatLngList.size() > 0) {
            for (Location location : LatLngList) {
                String locType = location.getLocType();
                String lat = location.getLat();
                String lng = location.getLng();
                LOG.e(TAG, "出发 latlng:lat=" + lat + "  lng=" + lng);
                double latDouble;
                double lngDouble;
                try {
                    latDouble = Double.parseDouble(lat);
                    lngDouble = Double.parseDouble(lng);
                } catch (Exception e) {
                    e.printStackTrace();
                    latDouble = 0;
                    lngDouble = 0;
                }

                MarkerOptions markerOptions = new MarkerOptions();
                //如果是分时租车，并且订单状态是行程中－，并且type是乘客，那么就不标记
                if (!( mLastRideStatus > OrderRideStatus.UN_TAKEN_VALUE
                        && MarkerType.USER.equals(locType))) {
                    markerOptions
                            .setFlat(true)
                            .draggable(false)
                            .position(new LatLng(latDouble, lngDouble))
                            .icon(BitmapDescriptorFactory.
                                    fromResource(getMarkerIconResId(MarkerCategory.DEPART, locType)));
                }
                mMarkerOptionsList.add(markerOptions);
            }
        }
    }

    private void addArrivedLoactionMarkerOptions(List<Location> eLatLngList) {
        if (eLatLngList != null && eLatLngList.size() > 0) {
            for (Location location : eLatLngList) {
                String locType = location.getLocType();
                String lat = location.getLat();
                String lng = location.getLng();
                LOG.e(TAG, "目的 elatlng:lat=" + lat + "  lng=" + lng);
                double latDouble;
                double lngDouble;
                try {
                    latDouble = Double.parseDouble(lat);
                    lngDouble = Double.parseDouble(lng);
                } catch (Exception e) {
                    e.printStackTrace();
                    latDouble = 0;
                    lngDouble = 0;
                }

                MarkerOptions markerOptions = new MarkerOptions();
                markerOptions
                        .setFlat(true)
                        .draggable(false)
                        .anchor(0.5f, 1f)
                        .position(new LatLng(latDouble, lngDouble))
                        .icon(BitmapDescriptorFactory.fromResource(
                                getMarkerIconResId(MarkerCategory.ARRIVAL, locType)
                        ));
                mMarkerOptionsList.add(markerOptions);
            }
        }
    }

    private void addMarker(AMap aMap) {
        for (MarkerOptions markerOptions : mMarkerOptionsList) {
            aMap.addMarker(markerOptions);
        }
    }

    private void refreshMarkShow() {
        if (isMarkShow) {
            return;
        }
        isMarkShow = true;
    }

    /**
     * 获取地图覆盖物对应的图标
     *
     * @param category
     * @param locType
     * @return
     */
    public
    @DrawableRes
    int getMarkerIconResId(int category, String locType) {
        if (!TextUtils.isEmpty(locType)) {
            int markerIconResId = 0;
            switch (locType) {
                case MarkerType.USER:
                    markerIconResId = category == MarkerCategory.DEPART
                            ? R.drawable.ic_shangche_location : R.drawable.ic_xiache_location;
                    break;
                case MarkerType.PARTNER:
                    markerIconResId = category == MarkerCategory.DEPART
                            ? R.drawable.ic_shangche_location : R.drawable.ic_xiache_location;
                    break;
                case MarkerType.CAR:
                    markerIconResId = category == MarkerCategory.DEPART
                            ? R.drawable.ic_express_car : 0;
                    break;
                default:
                    markerIconResId = 0;
            }
            return markerIconResId;
        }
        return 0;
    }


    /**
     * inner class
     */
    class ExpressCarHandler extends Handler {
        public ExpressCarHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int what = msg.what;
            if (what == WHAT_TCP_RESPONSE) {
                BizOrderResponse bizOrderResponse = (BizOrderResponse) msg.obj;
                scheduleUi(bizOrderResponse);
                scheduleMapView.renderDataOnSuccess(bizOrderResponse);
            }
        }

    }
}
